﻿// Copyright (c) Microsoft Corporation
//
// All rights reserved. 
//
// Licensed under the Apache License, Version 2.0 (the ""License""); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING 
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY 
// OR NON-INFRINGEMENT. 
//
// See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using TED.WindowsAzure.Unplugged.Mobile.Sync.Events;
using TED.WindowsAzure.Unplugged.Mobile.Sync.File;
using Windows.Storage;
using Windows.Storage.Streams;

namespace TED.WindowsAzure.Unplugged.Mobile.Sync.Folder
{
    public interface ISyncFolder
    {
        /// <summary>
        ///     The name of the physical folder in Local and Remote Storage
        /// </summary>
        string FolderName { get; }

        /// <summary>
        ///     Returns all local files in the LocalStorageFolder
        /// </summary>
        /// <returns></returns>
        Task<IEnumerable<ISyncFile>> ReadAsync();

        /// <summary>
        ///     Returns a single or null file based on an Id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<ISyncFile> LookupAsync(int id);

        /// <summary>
        ///     Returns a single or null file based on it's file name
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        Task<ISyncFile> LookupAsync(string name);

        /// <summary>
        ///     Pushes all locally modified items in the Folder to the associated
        ///     remote Folder.
        /// </summary>
        /// <returns>
        ///     A task that completes when the push operation has finished.
        /// </returns>
        Task PushAsync();

        /// <summary>
        ///     Pulls all remotely modified items from the associated
        ///     remote Folder.
        /// </summary>
        /// <returns>
        ///     A task that completes when the pull operation has finished.
        /// </returns>
        Task PullAsync();

        /// <summary>
        ///     Removes all items from the local Folder.
        /// </summary>
        /// <returns>
        ///     A task that completes when the truncate operation has finished.
        /// </returns>
        Task TruncateAsync();

        /// <summary>
        ///     Creates a 'undefined' (not inserted) local file based on a user defined name
        ///     If the file is found then the status of the file is still marked as undefined but its original status is stored.
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        Task<ISyncFile> CreateFileAsync(string fileName);

        /// <summary>
        ///     Opens a readable stream containing the specified instance of the file
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        Task<IRandomAccessStream> OpenReadAsync(ISyncFile instance);

        Task<IRandomAccessStream> OpenWriteAsync(ISyncFile instance);

        Task<IStorageFile> GetInternalStorageFile(ISyncFile instance);

        Task DeleteAsync(ISyncFile instance);

        /// <summary>
        ///     Insert a file and mark ready to sync
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        Task InsertAndCommitAsync(ISyncFile instance, IRandomAccessStream source);

        /// <summary>
        ///     Update a file and mark it ready to sync
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        Task UpdateAndCommitAsync(ISyncFile instance, IRandomAccessStream source);

        /// <summary>
        ///     Marks all files which are undefined as ready to Sync (inserted or updated)
        /// </summary>
        /// <returns></returns>
        Task FlushAsync();

        /// <summary>
        ///     Undo all work in progress files - this only marks the state of the files back to their previous state
        /// </summary>
        /// <returns></returns>
        Task CancelAsync();

        /// <summary>
        ///     Undo changes to a file - this only marks the state of the file back to it's previous state
        /// </summary>
        /// <returns></returns>
        Task UndoAsync(ISyncFile instance);

        /// <summary>
        ///     Marks the file as ready to sync (inserted or updated based on previous state)
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        Task CommitAsync(ISyncFile instance);

        /// <summary>
        ///     Occurs when the pull has started.
        /// </summary>
        event EventHandler<SyncStartedEventArgs> PullStarted;

        /// <summary>
        ///     Occurs every time pull has a progress on one file.
        /// </summary>
        event EventHandler<SyncProgressEventArgs> PullProgressChanged;

        /// <summary>
        ///     Occurs when the pull is completed.
        /// </summary>
        event EventHandler<SyncCompletedEventArgs> PullCompleted;

        /// <summary>
        ///     Occurs when the push has started.
        /// </summary>
        event EventHandler<SyncStartedEventArgs> PushStarted;

        /// <summary>
        ///     Occurs every time push has a progress on one file.
        /// </summary>
        event EventHandler<SyncProgressEventArgs> PushProgressChanged;

        /// <summary>
        ///     Occurs when the push is completed.
        /// </summary>
        event EventHandler<SyncCompletedEventArgs> PushCompleted;

        /// <summary>
        ///     Occurs when list of files to be synchronized has been built.
        /// </summary>
        event EventHandler<SyncListBuiltEventArgs> SyncListBuilt;

        /// <summary>
        ///     Occurs when list of files to be synchronized has been built.
        /// </summary>
        event EventHandler<SyncConnectionEventArgs> SyncConnection;
    }
}